package com.aqie.appletserver.service.impl;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.crypto.digest.MD5;
import com.aqie.appletserver.bean.request.TencentVoiceTranslateRequest;
import com.aqie.appletserver.bean.response.TencentVoiceTranslateResponse;
import com.aqie.appletserver.service.ITencentApiService;
import com.aqie.appletserver.utils.BeanUtils;
import com.aqie.appletserver.utils.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.beans.IntrospectionException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;

/**
 * https://www.imooc.com/article/21834
 */
@Service
@Slf4j
public class TencentApiService implements ITencentApiService {
    @Autowired
    private RestTemplate restTemplate;

    private String VOICE_TRANS = "https://api.ai.qq.com/fcgi-bin/nlp/nlp_speechtranslate";

    private String APP_KEY = "KOPUITFdBnvvAMTM";

    @Override
    public TencentVoiceTranslateResponse voiceTranslate(TencentVoiceTranslateRequest request, String filePath) throws IOException {
        HttpEntity<MultiValueMap<String, Object>> multiValueMapHttpEntity = getMultiValueMapHttpEntity(filePath, request);


        ResponseEntity<TencentVoiceTranslateResponse> response =
                restTemplate.postForEntity(VOICE_TRANS, multiValueMapHttpEntity, TencentVoiceTranslateResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    private Map<String, Object> getStringObjectMap(TencentVoiceTranslateRequest request) {
        Map<String, Object> map = new HashMap<>();
        try {
            map = BeanUtils.convertBean(request);
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return map;
    }


    public String getReqSign(Map<String, Object> map) {
        TreeMap<String, Object> treeMap = new TreeMap<>(map);
        StringBuffer sb = new StringBuffer();
        treeMap.forEach((k, v) -> {
            if (v != null && StrUtil.isNotBlank(String.valueOf(v))) {
                sb.append(k).append("=").append(URLUtil.encodeAll(String.valueOf(v))).append("&");
            }
        });
        sb.append("app_key=").append(APP_KEY);
        // log.info("url: {}", sb.toString());
        String sign = MD5.create().digestHex(sb.toString()).toUpperCase();
        // log.info("生成签名 " + sign);
        return sign;
    }


    private HttpEntity<MultiValueMap<String, Object>> getMultiValueMapHttpEntity(String filePath, TencentVoiceTranslateRequest request) throws IOException {
        byte[] bytes = FileUtils.readFileByBytes(filePath);
        String encode = Base64Encoder.encode(bytes);
        request.setSpeech_chunk(encode);
        // 对象转map
        Map<String, Object> map = getStringObjectMap(request);

        MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
        for (Map.Entry<String, Object> entry : map.entrySet()){
            postParameters.add(entry.getKey(), entry.getValue());
        }

        // 获取签名
        String sign = getReqSign(map);

        postParameters.add("sign", sign);
        // log.info("request:{}", postParameters);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_FORM_URLENCODED);

        return new HttpEntity<>(postParameters, headers);
    }
}
